<?php
declare (strict_types = 1);

namespace app\service\logic\common\user;

use app\model\communal\UserTokenModel;
use app\service\logic\BaseService;
use app\service\logic\common\order\OrderCourseService;
use app\service\logic\common\order\OrderMultiService;
use thans\jwt\Token;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

final class UserService extends BaseService
{
    protected string $modelClassName = 'UserModel';

    /**
     * @param $userId
     * @return array
     */
    public function getNumberByUserId($userId)
    {
        // 我的关注数量
        $expertFollowCount = invoke(ExpertFollowService::class)->getCount(['user_id'], ['user_id' => $userId]);
        $courseCollectCount = invoke(CourseCollectService::class)->getCount(['user_id'], ['user_id' => $userId]);

        // 我的测试数量
        $orderMultiCount = invoke(OrderMultiService::class)->getCount(['user_id'], ['user_id' => $userId]);
        // 我的课程数量
        $orderCourseCount = invoke(OrderCourseService::class)->getCount(['user_id', 'type'], ['user_id' => $userId, 'type' => 3]);

        return [
            'focus_on_count' => $expertFollowCount + $courseCollectCount,
            'order_multi_count' => $orderMultiCount,
            'order_course_count' => $orderCourseCount,
        ];
    }

    /**
     * 用户token入库
     *
     * @param $id
     * @param $token
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function insertAccessTokenByID($id, $token)
    {
        $loginsNumber = UserTokenModel::where('uid', $id)->count();
        $loginLimit = config('logic.user_login_limit');
        if ($loginsNumber >= $loginLimit) {
            // token logout
            $deleteNumber = (int)($loginsNumber - $loginLimit + 1);
            // 仅保留最新
            $deleteList = UserTokenModel::field(['uid', 'token', 'created_at'])
                ->where('uid', $id)
                ->order(['created_at' => 'asc'])
                ->limit($deleteNumber)->select();
            $this->deleteAccessTokenByCollection($deleteList);
        }
        UserTokenModel::create([
            'uid' => $id,
            'token' => $token,
        ]);
        return true;
    }

    /**
     * 根据Collection删除并禁用管理员Token
     *
     * @param Collection $collection
     * @return bool
     */
    public function deleteAccessTokenByCollection(Collection $collection)
    {
        foreach ($collection as $key=>$model) {
            $token = $model['token'];
            auth('user')->invalidate($token);
            $model->where('token', $token)->delete();
        }

        return true;
    }

    /**
     * delete cleaning token
     *
     * @param Token $token
     * @return bool
     */
    public function deleteAccessTokenByToken(Token $token)
    {
        $token = (string)$token;
        auth('user')->invalidate($token);
        return UserTokenModel::where('token', $token)->delete();
    }
}
